/**
 * 值为null或undefined时，返回 true
 * @param {*} value 
 */
function isInexact(value) {
    return value === null || value === undefined
}
/**
 * 对象为空时报错，否则返回该对象
 * @param {*} obj 
 */
function requireNonNull(obj) {
    if (isInexact(obj)) {
        throw new Error('Value cannot be null or undefined')
    }
    return obj
}

class Optional {
    constructor(value) {
        this.value = value
    }
    static of(value) {
        return new Optional(value)
    }
    isPresent() {
        return !isInexact(this.value)
    }
    static ofNullable(value) {
        return isInexact(value) ? Optional.of(null) : Optional.of(value)
    }
    get() {
        if (!this.isPresent()) {
            throw new Error('No value present')
        }
        return this.value
    }

    map(f) {
        requireNonNull(f)
        if (!this.isPresent()) {
            return Optional.of(null)
        } else {
            return Optional.ofNullable(f(this.value))
        }
    }
    orElse(other) {
        return this.isPresent() ? this.value : other
    }
    orElseGet(other) {
        return this.isPresent() ? this.value : other()
    }
}

function opt(value) {
    return Optional.ofNullable(value)
}

module.exports = {
    isInexact,
    opt
}